home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / amivogl-mdev / drivers / x11.c < prev   
C/C++ Source or Header  |  1998-01-12  |  22KB  |  1,161 lines

  1. /*
  2.  * VOGL/VOGLE driver for X11.
  3.  * 
  4.  * Define VOGLE if this driver is really for the VOGLE Libarary.
  5.  *
  6.  */
  7. #define VOGLE 1
  8.  
  9. #include <stdio.h>
  10. #include <X11/Xlib.h>
  11. #include <X11/Xutil.h>
  12.  
  13. #ifdef VOGLE
  14.  
  15. #include "vogle.h"
  16. static    char    *me = "vogle";
  17. #define LARGEFONT       "-adobe-courier-medium-r-normal--24-240-75-75-m-150-iso8859-1"
  18. #define SMALLFONT       "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1"
  19.  
  20. #else
  21.  
  22. #include "vogl.h"
  23. static    char    *me = "vogl";
  24. #define LARGEFONT    "9x15bold"
  25. #define SMALLFONT    "6x13bold"
  26.  
  27. #endif
  28.  
  29. #define MIN(x,y)    ((x) < (y) ? (x) : (y))
  30. #define MAX(x,y)    ((x) > (y) ? (x) : (y))
  31. #define    CMAPSIZE    256
  32. #define    EV_MASK        KeyPressMask|ButtonReleaseMask|ExposureMask|ButtonPressMask
  33.  
  34. static    int        maxw = -1, maxh = -1;
  35. static    Window        winder;
  36. static    Display        *display;
  37. static    int        screen;
  38. static    unsigned long    carray[CMAPSIZE];
  39. static    Colormap    colormap;
  40.  
  41. static    Drawable    theDrawable = -1;
  42. static    GC        theGC;
  43. static    XGCValues    theGCvalues;
  44. static    Pixmap        bbuf;        /* Back buffer pixmap */
  45. static    int        back_used = 0;    /* Have we backbuffered ? */
  46.  
  47. static    XFontStruct    *font_id = (XFontStruct *)NULL;
  48. XEvent            event;
  49.  
  50. static    unsigned long    colour;
  51. static    unsigned int    h, w;
  52. static    char        *smallf, *largef;
  53. static    char        use_toolkit_win = 0;
  54.  
  55. /*
  56.  * vo_xt_set_win
  57.  *
  58.  *    Just sets the drawable to the partucular window.
  59.  */
  60. int vo_xt_set_win(
  61.   Display *dis,
  62.   Drawable win,
  63.   int xw,
  64.   int xh)
  65. {
  66.     int    backb;
  67.  
  68.     backb = (theDrawable == bbuf);
  69.  
  70.     winder = win;
  71.  
  72.     vdevice.sizeX = vdevice.sizeY = MIN(xh, xw);
  73.     vdevice.sizeSx = xw;
  74.     vdevice.sizeSy = xh;
  75.  
  76.         if (xw > maxw || xh > maxh) {
  77.         if (back_used) {
  78.             back_used = 0;
  79.             XFreePixmap(display, bbuf);
  80.             X11_backbuf();
  81.         }
  82.         }
  83.  
  84.     display = dis;
  85.     if (backb)
  86.         theDrawable = bbuf;
  87.     else
  88.         theDrawable = win;
  89.  
  90.     return(1);
  91. }
  92.  
  93. /*
  94.  * vo_xt_window
  95.  *
  96.  *    Tells VOGL/VOGLE to use a window from an X11 toolkit (eg xview)
  97.  *    and not to make it's own window.
  98.  */
  99. int vo_xt_window(
  100.   Display *dis,
  101.   Window win,
  102.   int xw,
  103.   int xh)
  104. {
  105.     int    backb, i, depth;
  106.  
  107.     backb = (theDrawable == bbuf);
  108.  
  109.     display = dis;
  110.     winder = win;
  111.     screen = DefaultScreen(display);
  112.     colormap = DefaultColormap(display, screen);
  113.     depth = vdevice.depth = DefaultDepth(display, screen);
  114.     theDrawable = winder;
  115.  
  116.     use_toolkit_win = 1;
  117.     w = xw;
  118.     h = xh;
  119.  
  120.     /*
  121.      * Set our standard colors...
  122.      */
  123.     if (vdevice.depth == 1) {
  124.         /*
  125.          * Black and white - anything that's not black is white.
  126.          */
  127.         carray[0] = BlackPixel(display, screen);
  128.         for (i = 1; i < CMAPSIZE; i++)
  129.             carray[i] = WhitePixel(display, screen);
  130.     } else {
  131.         /*
  132.          * Color, try to get our colors close to what's in the
  133.          * default colormap.
  134.          */
  135.         X11_mapcolor(0, 0, 0, 0);
  136.         X11_mapcolor(1, 255, 0, 0);
  137.         X11_mapcolor(2, 0, 255, 0);
  138.         X11_mapcolor(3, 255, 255, 0);
  139.         X11_mapcolor(4, 0, 0, 255);
  140.         X11_mapcolor(5, 255, 0, 255);
  141.         X11_mapcolor(6, 0, 255, 255);
  142.         X11_mapcolor(7, 255, 255, 255);
  143.     }
  144.  
  145.     if ((smallf = XGetDefault(display, me, "smallfont")) == (char *)NULL)
  146.         smallf = SMALLFONT;
  147.  
  148.     if ((largef = XGetDefault(display, me, "largefont")) == (char *)NULL)
  149.         largef = LARGEFONT;
  150.  
  151.     /*
  152.      * Create Graphics Context and Drawable
  153.      */
  154.     theGC = XDefaultGC(display, screen);
  155.     theGCvalues.graphics_exposures = False;
  156.     theGCvalues.cap_style = CapButt;
  157.     XChangeGC(display, theGC, GCGraphicsExposures|GCCapStyle, &theGCvalues);
  158.     X11_color(0);
  159.  
  160.     vdevice.sizeX = vdevice.sizeY = MIN(xh, xw);
  161.     vdevice.sizeSx = xw;
  162.     vdevice.sizeSy = xh;
  163.  
  164.         if (back_used && (xw > maxw || xh > maxh)) {
  165.                 back_used = 0;
  166.         XFreePixmap(display, bbuf);
  167.                 X11_backbuf();
  168.         }
  169.  
  170.     if (backb)
  171.         theDrawable = bbuf;
  172.     else
  173.         theDrawable = win;
  174.  
  175.  
  176. #ifndef VOGLE
  177.     vdevice.devname = "X11";
  178. #endif
  179.  
  180.     return(1);
  181. }
  182.  
  183. /*
  184.  *    vo_xt_win_size
  185.  *
  186.  * If the X toolkit has changed the window size, then
  187.  * you might wish to call this routine to tell vogl/vogle about it.
  188.  */
  189. int vo_xt_win_size(
  190.   int xw,
  191.   int xh)
  192. {
  193.     char    backb;
  194.  
  195.     w = xw;
  196.     h = xh;
  197.  
  198.     vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  199.     vdevice.sizeSx = w;
  200.     vdevice.sizeSy = h;
  201.  
  202.     backb = (theDrawable == bbuf);
  203.  
  204.     if (back_used) {
  205.  
  206.         /* Have to re allocate the back buffer */
  207.  
  208.         XFreePixmap(display, bbuf);
  209.  
  210.         bbuf = XCreatePixmap(display,
  211.             (Drawable)winder,
  212.             (unsigned int)vdevice.sizeSx + 1,
  213.             (unsigned int)vdevice.sizeSy + 1,
  214.             (unsigned int)vdevice.depth
  215.         );
  216.     }
  217.     if (backb)
  218.         theDrawable = (Drawable)bbuf;
  219. }
  220.  
  221. /*
  222.  * return the X display in use.
  223.  */
  224. Display * vo_xt_get_display(void)
  225. {
  226.     return(display);
  227. }
  228.  
  229. /*
  230.  * return the X Window in use.
  231.  */
  232. Window * vo_xt_get_window(void)
  233. {
  234.     return(winder);
  235. }
  236.  
  237.  
  238. /*
  239.  * X11_init
  240.  *
  241.  *    initialises X11 display.
  242.  */
  243. int X11_init(void)
  244. {
  245.     int        i;
  246.     int        x, y, prefx, prefy, prefxs, prefys;
  247.     unsigned int    bw, depth, mask;
  248.     Window        rootw, childw;
  249.     char        *av[2], name[128], *geom;
  250.  
  251.     XSetWindowAttributes    theWindowAttributes;
  252.     XWindowAttributes    retWindowAttributes;
  253.         XSizeHints              theSizeHints;
  254.         unsigned long           theWindowMask;
  255.     XWMHints                theWMHints;
  256.  
  257.  
  258.     if (use_toolkit_win)
  259.         return(1);
  260.  
  261.     av[0] = me;
  262.     av[1] = (char *)NULL;
  263.  
  264.     if ((display = XOpenDisplay((char *)NULL)) == (Display *)NULL) {
  265.         fprintf(stderr,"%s: X11_init: can't connect to X server\n", me);
  266.         exit(1);
  267.     }
  268.  
  269.     screen = DefaultScreen(display);
  270.     winder = RootWindow(display, screen);
  271.     colormap = DefaultColormap(display, screen);
  272.     depth = vdevice.depth = DefaultDepth(display, screen);
  273.  
  274.     /*
  275.      * Set our standard colors...
  276.      */
  277.     if (vdevice.depth == 1) {
  278.         /*
  279.          * Black and white - anything that's not black is white.
  280.          */
  281.         carray[0] = BlackPixel(display, screen);
  282.         for (i = 1; i < CMAPSIZE; i++)
  283.             carray[i] = WhitePixel(display, screen);
  284.     } else {
  285.         /*
  286.          * Color, try to get our colors close to what's in the
  287.          * default colormap.
  288.          */
  289.         X11_mapcolor(0, 0, 0, 0);
  290.         X11_mapcolor(1, 255, 0, 0);
  291.         X11_mapcolor(2, 0, 255, 0);
  292.         X11_mapcolor(3, 255, 255, 0);
  293.         X11_mapcolor(4, 0, 0, 255);
  294.         X11_mapcolor(5, 255, 0, 255);
  295.         X11_mapcolor(6, 0, 255, 255);
  296.         X11_mapcolor(7, 255, 255, 255);
  297.     }
  298.  
  299.     getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  300.  
  301.     /*
  302.      * NEED TO USE XGRABPOINTER here???
  303.      */
  304.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
  305.  
  306.     if (childw == None)
  307.         childw = rootw;
  308.  
  309. /*
  310.     if (!XGetWindowAttributes(display, childw, &retWindowAttributes)) {
  311.         fprintf(stderr,"Can't get window attributes.");
  312.         exit(1);
  313.     }
  314.  
  315.     x = retWindowAttributes.x;
  316.     y = retWindowAttributes.y;
  317.     w = retWindowAttributes.width;
  318.     h = retWindowAttributes.height;
  319.     bw = retWindowAttributes.border_width;
  320.     depth = vdevice.depth = retWindowAttributes.depth;
  321.  
  322.     XTranslateCoordinates(display,
  323.             childw, retWindowAttributes.root,
  324.             0, 0,
  325.             &x, &y,
  326.             &rootw
  327.     );
  328. */
  329.  
  330.     XGetGeometry(display, childw, &rootw, &x, &y, &w, &h, &bw, &depth);
  331.  
  332.         theWindowAttributes.backing_store = WhenMapped;
  333.         theWindowAttributes.save_under = True;
  334.         theWindowAttributes.border_pixel = carray[1];
  335.  
  336.  
  337.     /*
  338.      * See if there is something in the .Xdefaults file regarding
  339.      * VOGL/VOGLE.
  340.      */
  341.  
  342.     if ((smallf = XGetDefault(display, me, "smallfont")) == (char *)NULL)
  343.         smallf = SMALLFONT;
  344.  
  345.     if ((largef = XGetDefault(display, me, "largefont")) == (char *)NULL)
  346.         largef = LARGEFONT;
  347.  
  348.     geom = XGetDefault(display, me, "Geometry");
  349.  
  350.     if (geom != (char *)NULL) {
  351.         mask = XParseGeometry(geom, &x, &y, &w, &h);
  352.  
  353.         if (mask & XValue)
  354.             theSizeHints.flags |= USPosition;
  355.  
  356.         if (mask & YValue)
  357.             theSizeHints.flags |= USPosition;
  358.  
  359.         if (mask & WidthValue)
  360.             theSizeHints.flags |= USSize;
  361.  
  362.         if (mask & HeightValue)
  363.             theSizeHints.flags |= USSize;
  364.  
  365.         if (mask & XNegative)
  366.              x = DisplayWidth(display, screen) - 2*bw - w + x;
  367.  
  368.         if (mask & YNegative)
  369.             y = DisplayHeight(display, screen) - 2*bw - h + y;
  370.  
  371.     } else
  372.         theSizeHints.flags = PPosition | PSize;
  373.  
  374.     if (prefx > -1) {
  375.             x = prefx;
  376.             y = prefy;
  377.     }
  378.  
  379.     if (prefxs > -1) {
  380.             w = prefxs;
  381.             h = prefys;
  382.     }
  383.  
  384.     if (bw == 0)
  385.         bw = 4;
  386.  
  387.     x -= bw;
  388.     y -= bw;
  389.  
  390.     if (x <= 0)
  391.         x = 0;
  392.  
  393.     if (y <= 0)
  394.         y = 0;
  395.  
  396.     w -= 4 * bw;
  397.     h -= 4 * bw;
  398.  
  399.         theWindowMask = CWBorderPixel|CWBackingStore;
  400.  
  401.         winder = XCreateWindow(display,
  402.                                 winder,
  403.                                 x, y,
  404.                                 w, h,
  405.                                 bw,
  406.                                 (int)vdevice.depth,
  407.                                 InputOutput,
  408.                                 CopyFromParent,
  409.                                 theWindowMask,
  410.                                 &theWindowAttributes
  411.                         );
  412.  
  413.         theSizeHints.x = x;
  414.         theSizeHints.y = y;
  415.         theSizeHints.width = w;
  416.         theSizeHints.height = h;
  417.  
  418. #ifndef VOGLE
  419.     if (vdevice.wintitle)
  420.         strcpy(name, vdevice.wintitle);
  421.     else
  422.         sprintf(name, "%s %d (win id 0x%x)", me, getpid(), winder);
  423. #else
  424.     sprintf(name, "%s %d (win id 0x%x)", me, getpid(), winder);
  425. #endif
  426.  
  427.     XSetStandardProperties(display,
  428.         winder,
  429.         name,
  430.         name,
  431.         None,
  432.         av,
  433.         1,
  434.         &theSizeHints
  435.     );
  436.  
  437.         theWMHints.initial_state = NormalState;
  438.         theWMHints.input = True;
  439.         theWMHints.flags = StateHint | InputHint;
  440.         XSetWMHints(display, winder, &theWMHints);
  441.  
  442.     XSelectInput(display, winder, EV_MASK);
  443.  
  444.     theDrawable = (Drawable)winder;
  445.  
  446.     /*
  447.      * Create Graphics Context and Drawable
  448.      */
  449.     theGC = XDefaultGC(display, screen);
  450.     theGCvalues.graphics_exposures = False;
  451.     theGCvalues.cap_style = CapButt;
  452.     XChangeGC(display, theGC, GCGraphicsExposures|GCCapStyle, &theGCvalues);
  453.     theDrawable = (Drawable)winder;
  454.     X11_color(0);
  455.  
  456.     XMapRaised(display, winder);
  457.     XFlush(display);
  458.  
  459.     /*
  460.      * Wait for Exposure event.
  461.      */
  462.     do {
  463.         XNextEvent(display, &event);
  464.     } while (event.type != Expose && event.type != MapNotify);
  465.  
  466.     /*
  467.      * Set the input Focus to us.
  468.  
  469.         if (prefx == -1 && prefxs == -1)
  470.                 XSetInputFocus(display, winder, RevertToParent, CurrentTime);
  471.      */
  472.  
  473.     /*
  474.      *  Let VOGL/VOGLE know about the window size.
  475.      *  (We may have been resized..... )
  476.      */
  477.     if (!XGetWindowAttributes(display, winder, &retWindowAttributes)) {
  478.         fprintf(stderr,"Can't get window attributes.");
  479.         exit(1);
  480.     }
  481.  
  482.     x = retWindowAttributes.x;
  483.     y = retWindowAttributes.y;
  484.     w = retWindowAttributes.width;
  485.     h = retWindowAttributes.height;
  486.  
  487.     XTranslateCoordinates(display,
  488.             winder, retWindowAttributes.root,
  489.             0, 0,
  490.             &x, &y,
  491.             &rootw
  492.     );
  493.  
  494.     vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  495.     vdevice.sizeSx = w;
  496.     vdevice.sizeSy = h;
  497.  
  498.     if (back_used && (maxw < w || maxh < h)) {
  499.         back_used = 0;
  500.         X11_backbuf();
  501.     }
  502.  
  503.     return(1);
  504. }
  505.  
  506. /*
  507.  * X11_exit
  508.  *
  509.  *    cleans up before returning the window to normal.
  510.  */
  511. int X11_exit(void)
  512. {
  513.     if (back_used) 
  514.         XFreePixmap(display, bbuf);
  515.  
  516.     if (font_id != (XFontStruct *)NULL)
  517.         XFreeFont(display, font_id);
  518.  
  519.     font_id = (XFontStruct *)NULL;
  520.  
  521.     if (use_toolkit_win)
  522.         return(1);
  523.  
  524.     XDestroyWindow(display, winder);
  525.  
  526.     XSync(display, 0);
  527.  
  528.     XCloseDisplay(display);
  529.  
  530.     display = (Display *)NULL;
  531.  
  532.     return(1);
  533. }
  534.  
  535. /*
  536.  * X11_draw
  537.  *
  538.  *    draws a line from the current graphics position to (x, y).
  539.  *
  540.  * Note: (0, 0) is defined as the top left of the window in X (easy
  541.  * to forget).
  542.  */
  543. int X11_draw(
  544.   int x,
  545.   int y)
  546. {
  547.     if (x == vdevice.cpVx && y == vdevice.cpVy)
  548.         /*
  549.          * Hack for some X servers... my MIT X11 R5 manual states:
  550.          * CapButt    the results are device-dependent, but the
  551.          *        desired effect is that a single pixel is
  552.          *        drawn.
  553.          *
  554.          * This does work on a real MIT R5 server... but on some
  555.          * machines, we have to do this XDrawPoint thing.
  556.          * (It's probably faster this way anyway).
  557.          */
  558.         XDrawPoint(display, theDrawable, theGC, x, vdevice.sizeSy - y);
  559.     else
  560.         XDrawLine(display,
  561.             theDrawable,
  562.             theGC,
  563.             vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  564.             x, vdevice.sizeSy - y
  565.         );
  566.  
  567.     if (vdevice.sync)
  568.         XSync(display, 0);
  569. }
  570.  
  571. int X11_pnt(
  572.   int x,
  573.   int y)
  574. {
  575.     XDrawPoint(display,
  576.         theDrawable,
  577.         theGC,
  578.         x, vdevice.sizeSy - y
  579.     );
  580.  
  581.     if (vdevice.sync)
  582.         XSync(display, 0);
  583. }
  584.  
  585. /*
  586.  * X11_getkey
  587.  *
  588.  *    grab a character from the keyboard - blocks until one is there.
  589.  */
  590. int X11_getkey(void)
  591. {
  592.     char    c;
  593.  
  594.     do {
  595.         XNextEvent(display, &event);
  596.         if (event.type == KeyPress) {
  597.             if (XLookupString((XKeyEvent *)&event, &c, 1, NULL, NULL) > 0)
  598.                 return((int)c);
  599.             else
  600.                 return(0);
  601.         }
  602.     } while (event.type != KeyPress);
  603. }
  604.  
  605. /*
  606.  * X11_checkkey
  607.  *
  608.  *    Check if there has been a keyboard key pressed.
  609.  *    and return it if there is.
  610.  */
  611. int X11_checkkey(void)
  612. {
  613.     char    c;
  614.  
  615.     if (!XCheckWindowEvent(display, winder, KeyPressMask, &event))
  616.         return(0);
  617.  
  618.     if (event.type == KeyPress)
  619.         if (XLookupString((XKeyEvent *)&event, &c, 1, NULL, NULL) > 0)
  620.             return((int)c);
  621.  
  622.     return(0);
  623. }
  624.  
  625. /*
  626.  * X11_locator
  627.  *
  628.  *    return the window location of the cursor, plus which mouse button,
  629.  * if any, is been pressed.
  630.  */
  631. int X11_locator(
  632.   int *wx,
  633.   int *wy)
  634. {
  635.     Window        rootw, childw;
  636.     int        x, y;
  637.     unsigned int    mask;
  638.  
  639.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, wx, wy, &mask);
  640.  
  641.     *wy = (int)vdevice.sizeSy - *wy;
  642.  
  643.     return(mask >> 8);
  644. }
  645.  
  646. #ifdef VOGLE
  647. /*
  648.  * X11_clear
  649.  *
  650.  * Clear the screen (or current buffer )to current colour
  651.  */
  652. int X11_clear(void)
  653. {
  654.     XSetBackground(display, theGC, colour);
  655.     XFillRectangle(display,
  656.         theDrawable,
  657.         theGC,
  658.         0,
  659.         0,
  660.         (unsigned int)vdevice.sizeSx + 1,
  661.         (unsigned int)vdevice.sizeSy + 1
  662.     );
  663.  
  664.     if (vdevice.sync)
  665.         XFlush(display);
  666. }
  667.  
  668. #else 
  669.  
  670. /*
  671.  * X11_clear
  672.  *
  673.  * Clear the screen (or current buffer )to current colour
  674.  */
  675. int X11_clear(void)
  676. {
  677.     unsigned int    w = vdevice.maxVx - vdevice.minVx;
  678.     unsigned int    h = vdevice.maxVy - vdevice.minVy;
  679.  
  680.     XSetBackground(display, theGC, colour);
  681.  
  682.     XFillRectangle(display,
  683.         theDrawable,
  684.         theGC,
  685.         vdevice.minVx,
  686.         vdevice.sizeSy - vdevice.maxVy, 
  687.         w, 
  688.         h
  689.     );
  690.  
  691.     if (vdevice.sync)
  692.         XFlush(display);
  693. }
  694. #endif
  695.  
  696. /*
  697.  * X11_color
  698.  *
  699.  *    set the current drawing color index.
  700.  */
  701. int X11_color(int ind)
  702. {
  703.     colour = carray[ind];
  704.     XSetForeground(display, theGC, colour);
  705. }
  706.  
  707. /*
  708.  * X11_mapcolor
  709.  *
  710.  *    change index i in the color map to the appropriate r, g, b, value.
  711.  */
  712. int X11_mapcolor(
  713.   int i,
  714.   int r,
  715.   int g,
  716.   int b)
  717. {
  718.     int    stat;
  719.     XColor    tmp;
  720.  
  721.     if (i >= CMAPSIZE)
  722.         return(-1);
  723.  
  724.  
  725.     /*
  726.      * For Black and White.
  727.      * If the index is 0 and r,g,b != 0 then we are remapping black.
  728.      * If the index != 0 and r,g,b == 0 then we make it black.
  729.      */
  730.     if (vdevice.depth == 1) {
  731.         if (i == 0 && (r != 0 || g != 0 || b != 0)) 
  732.             carray[i] = WhitePixel(display, screen);
  733.         else if (i != 0 && r == 0 && g == 0 && b == 0)
  734.             carray[i] = BlackPixel(display, screen);
  735.     } else {
  736.         tmp.red = (unsigned short)(r / 255.0 * 65535);
  737.         tmp.green = (unsigned short)(g / 255.0 * 65535);
  738.         tmp.blue = (unsigned short)(b / 255.0 * 65535);
  739.         tmp.flags = 0;
  740.         tmp.pixel = (unsigned long)i;
  741.  
  742.         if ((stat = XAllocColor(display, colormap, &tmp)) == 0) {
  743.             fprintf(stderr, "XAllocColor failed (status = %d)\n", stat);
  744.             exit(1);
  745.         }
  746.         carray[i] = tmp.pixel;
  747.     }
  748.  
  749.     XFlush(display);
  750.     return(0);
  751. }
  752.     
  753. /*
  754.  * X11_font
  755.  *
  756.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  757.  *
  758.  */
  759. int X11_font(char *fontfile)
  760. {
  761.     XGCValues    xgcvals;
  762.     char    *name = fontfile;
  763.  
  764.     if (font_id != (XFontStruct *)NULL)
  765.         XFreeFont(display, font_id);
  766.  
  767.     if (strcmp(fontfile, "small") == 0) {
  768.         if ((font_id = XLoadQueryFont(display, smallf)) == (XFontStruct *)NULL) {
  769.             fprintf(stderr, "%s X11.c couldn't open small font '%s'\n", me, smallf);
  770.             fprintf(stderr, "You'll have to redefine it....\n");
  771.             return(0);
  772.         } else
  773.             name = smallf;
  774.         
  775.     } else if (strcmp(fontfile, "large") == 0) {
  776.         if ((font_id = XLoadQueryFont(display, largef)) == (XFontStruct *)NULL) {
  777.             fprintf(stderr, "%s X11.c couldn't open large font '%s'\n", me, largef);
  778.             fprintf(stderr, "You'll have to redefine it....\n");
  779.             return(0);
  780.         }
  781.             name = largef;
  782.     } else {
  783.         if ((font_id = XLoadQueryFont(display, fontfile)) == (XFontStruct *)NULL) {
  784.             fprintf(stderr, "%s X11.c couldn't open fontfile '%s'\n", me, fontfile);
  785.             return(0);
  786.         }
  787.     }
  788.  
  789.     /*
  790.     vdevice.hheight = font_id->max_bounds.ascent + font_id->max_bounds.descent;
  791.     */
  792.     vdevice.hheight = font_id->ascent + font_id->descent;
  793.     vdevice.hwidth = font_id->max_bounds.width;
  794.  
  795.  
  796.     xgcvals.font = XLoadFont(display, name);
  797.     XChangeGC(display, theGC, GCFont, &xgcvals);
  798.  
  799.     return(1);
  800. }
  801.  
  802. /* 
  803.  * X11_char
  804.  *
  805.  *     outputs one char - is more complicated for other devices
  806.  */
  807. int X11_char(char c)
  808. {
  809.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), &c, 1);
  810.  
  811.     if (vdevice.sync)
  812.         XFlush(display);
  813. }
  814.  
  815. /*
  816.  * X11_string
  817.  *
  818.  *    Display a string at the current drawing position.
  819.  */
  820. int X11_string(char s[])
  821. {
  822.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, strlen(s));
  823.     if (vdevice.sync)
  824.         XFlush(display);
  825. }
  826.  
  827. /*
  828.  * X11_fill
  829.  *
  830.  *    fill a polygon
  831.  */
  832. int X11_fill(
  833.   int n,
  834.   int x[],
  835.   int y[])
  836. {
  837.     char    buf[BUFSIZ];
  838.     XPoint    plist[128];
  839.     int    i;
  840.  
  841.     if (n > 128) {
  842.         sprintf(buf, "%s: more than 128 points in a polygon", me);
  843.         verror(buf);
  844.     }
  845.  
  846.     for (i = 0; i < n; i++) {
  847.         plist[i].x = x[i];
  848.         plist[i].y = vdevice.sizeSy - y[i];
  849.     }
  850.  
  851.     XFillPolygon(display, theDrawable, theGC, plist, n, Nonconvex, CoordModeOrigin);
  852.  
  853.     vdevice.cpVx = x[n-1];
  854.     vdevice.cpVy = y[n-1];
  855.  
  856.     if (vdevice.sync)
  857.         XFlush(display);
  858. }
  859.  
  860. /*
  861.  * X11_backbuf
  862.  *
  863.  *    Set up double buffering by allocating the back buffer and
  864.  *    setting drawing into it.
  865.  */
  866. int X11_backbuf(void)
  867. {
  868.     if (!back_used) {
  869.         bbuf = XCreatePixmap(display,
  870.             (Drawable)winder,
  871.             (unsigned int)vdevice.sizeSx + 1,
  872.             (unsigned int)vdevice.sizeSy + 1,
  873.             (unsigned int)vdevice.depth
  874.         );
  875.  
  876.         maxw = MAX(vdevice.sizeSx + 1, maxw);
  877.         maxh = MAX(vdevice.sizeSy + 1, maxh);
  878.     }
  879.  
  880.     theDrawable = (Drawable)bbuf;
  881.  
  882.     back_used = 1;
  883.  
  884.     return(1);
  885. }
  886.  
  887. /*
  888.  * X11_swapbuf
  889.  *
  890.  *    Swap the back and from buffers. (Really, just copy the
  891.  *    back buffer to the screen).
  892.  */
  893. int X11_swapbuf(void)
  894. {
  895.     XCopyArea(display,
  896.         theDrawable,
  897.         winder,
  898.         theGC,
  899.         0, 0,
  900.         (unsigned int)vdevice.sizeSx + 1,
  901.         (unsigned int)vdevice.sizeSy + 1,
  902.         0, 0
  903.     );
  904.     XSync(display, 0);
  905. }
  906.  
  907. /*
  908.  * X11_frontbuf
  909.  *
  910.  *    Make sure we draw to the screen.
  911.  */
  912. int X11_frontbuf(void)
  913. {
  914.     theDrawable = (Drawable)winder;
  915. }
  916.  
  917. /*
  918.  * Syncronise the display with what we think has been sent to it...
  919.  */
  920. int X11_sync(void)
  921. {
  922.     XSync(display, 0);
  923. }
  924.  
  925. #undef VORTDUMP
  926. #ifdef VORTDUMP
  927. /*
  928.  * HACK
  929.  * Dump the contents of the current buffer to a VORT file....
  930.  * ONLY WORKS WITH 8Bit Drawables!
  931.  */
  932. #include "vort.h"
  933.  
  934. int X11_dump_pixmap(
  935.   char *filename,
  936.   int dx,
  937.   int dy,
  938.   int dw,
  939.   int dh)
  940. {
  941.     XImage    *ximage;
  942.     image    *im;
  943.     unsigned char    *line, *rm, *gm, *bm;
  944.     XColor    *cols;
  945.     int    i;
  946.  
  947.     if (dw > vdevice.sizeSx || dw < 0)
  948.         dw = vdevice.sizeSx;
  949.     if (dh > vdevice.sizeSy || dh < 0)
  950.         dh = vdevice.sizeSy;
  951.  
  952.     if (dx > vdevice.sizeSx || dx < 0)
  953.         dx = 0;
  954.     if (dy > vdevice.sizeSy || dy < 0)
  955.         dy = 0;
  956.  
  957.     ximage = XGetImage(display, 
  958.             theDrawable, 
  959.             dx, dy,
  960.             (unsigned int)dw,
  961.             (unsigned int)dh,
  962.             AllPlanes,
  963.             ZPixmap
  964.         );
  965.  
  966.     if (!ximage) {
  967.         fprintf(stderr, "X11_dump_pixmap: can't do XGetImage\n");
  968.         exit(1);
  969.     }
  970.  
  971.     if ((im = openimage(filename, "w")) == (image *)NULL) {
  972.         fprintf(stderr, "X11_dump_pixmap: can't open %s\n", filename);
  973.         exit(1);
  974.     }
  975.  
  976.     if (!(rm = (unsigned char *)malloc(256))) {
  977.         fprintf(stderr, "X11_dump_pixmap: can't alloc rm\n");
  978.         exit(1);
  979.     }
  980.     if (!(gm = (unsigned char *)malloc(256))) {
  981.         fprintf(stderr, "X11_dump_pixmap: can't alloc gm\n");
  982.         exit(1);
  983.     }
  984.     if (!(bm = (unsigned char *)malloc(256))) {
  985.         fprintf(stderr, "X11_dump_pixmap: can't alloc bm\n");
  986.         exit(1);
  987.     }
  988.     if (!(cols = (XColor *)malloc(256 * sizeof(XColor)))) {
  989.         fprintf(stderr, "X11_dump_pixmap: can't alloc cols\n");
  990.         exit(1);
  991.     }
  992.  
  993.     /*
  994.      * Get our colormap...
  995.      */
  996.     for (i = 0; i < 256; i++) {
  997.         cols[i].pixel = (unsigned long)i;
  998.         cols[i].red = cols[i].green = cols[i].blue = 0;
  999.         cols[i].flags = DoRed | DoGreen | DoBlue;
  1000.     }
  1001.  
  1002.     XQueryColors(display, colormap, cols, 256);
  1003.  
  1004.     for (i = 0; i < 256; i++) {
  1005.         rm[i] = (unsigned char)(cols[i].red >> 8);
  1006.         gm[i] = (unsigned char)(cols[i].green >> 8);
  1007.         bm[i] = (unsigned char)(cols[i].blue >> 8);
  1008.     }
  1009.  
  1010.     imagetype(im) = PIX_RLECMAP;
  1011.     imageheight(im) = dh;
  1012.     imagewidth(im) = dw;
  1013.     imagedate(im) = time(0);
  1014.     titlelength(im) = 0;
  1015.     setcmap(im, 256, rm, gm, bm);
  1016.  
  1017.     writeheader(im);
  1018.  
  1019.     line = (unsigned char *)ximage->data;
  1020.     for (i = 0; i < dh; i++) {
  1021.         writemappedline(im, line);
  1022.         line += ximage->bytes_per_line;
  1023.     }
  1024.     
  1025.     closeimage(im); 
  1026.  
  1027.     free(rm);
  1028.     free(gm);
  1029.     free(bm);
  1030.     free(cols);
  1031. }
  1032.  
  1033. #endif
  1034.  
  1035. #ifndef VOGLE
  1036. /*
  1037.  * X11_setlw
  1038.  *
  1039.  *    Set the line width....
  1040.  */
  1041. int X11_setlw(int w)
  1042. {
  1043.     XGCValues vals;
  1044.  
  1045.     vals.line_width = w;
  1046.     XChangeGC(display, theGC, GCLineWidth, &vals);
  1047. }
  1048.  
  1049. /*
  1050.  * X11_setls
  1051.  *
  1052.  *    Set the line style....
  1053.  */
  1054.  
  1055. int X11_setls(int lss)
  1056. {
  1057.     unsigned ls = lss;
  1058.     char    dashes[16];
  1059.     int    i, n, a, b, offset;
  1060.  
  1061.     if (ls == 0xffff) {
  1062.         XSetLineAttributes(display, theGC, vdevice.attr->a.lw, LineSolid, CapButt, JoinMiter);
  1063.         return;
  1064.     }
  1065.  
  1066.     for (i = 0; i < 16; i++)
  1067.         dashes[i] = 0;
  1068.  
  1069.     for (i = 0; i < 16; i++)    /* Over 16 bits */
  1070.         if ((ls & (1 << i)))
  1071.             break;
  1072.  
  1073.     offset = i;
  1074.  
  1075. #define    ON    1
  1076. #define    OFF    0
  1077.         
  1078.     a = b = OFF;
  1079.     if (ls & (1 << 0))
  1080.         a = b = ON;
  1081.  
  1082.     n = 0;
  1083.     for (i = 0; i < 16; i++) {    /* Over 16 bits */
  1084.         if (ls & (1 << i))
  1085.             a = ON;
  1086.         else
  1087.             a = OFF;
  1088.  
  1089.         if (a != b) {
  1090.             b = a;
  1091.             n++;
  1092.         }
  1093.         dashes[n]++;
  1094.     }
  1095.     n++;
  1096.  
  1097.     XSetLineAttributes(display, theGC, vdevice.attr->a.lw, LineOnOffDash, CapButt, JoinMiter);
  1098.     XSetDashes(display, theGC, offset, dashes, n);
  1099. }
  1100.  
  1101. #else
  1102. /*
  1103.  * X11_setlw (this one for VOGLE only)
  1104.  *
  1105.  *    Set the line width....THICK or THIN
  1106.  */
  1107. int X11_setlw(int w)
  1108. {
  1109.     XGCValues vals;
  1110.  
  1111.     if (w == 0)
  1112.         w = 1;
  1113.     else if (w == 1)
  1114.         w = 2;
  1115.  
  1116.     vals.line_width = w;
  1117.     XChangeGC(display, theGC, GCLineWidth, &vals);
  1118. }
  1119.  
  1120. #endif 
  1121.  
  1122. /*
  1123.  * the device entry
  1124.  */
  1125. static DevEntry X11dev = {
  1126.     "X11",
  1127.     "large",
  1128.     "small",
  1129.     X11_backbuf,
  1130.     X11_char,
  1131.     X11_checkkey,
  1132.     X11_clear,
  1133.     X11_color,
  1134.     X11_draw,
  1135.     X11_exit,
  1136.     X11_fill,
  1137.     X11_font,
  1138.     X11_frontbuf,
  1139.     X11_getkey,
  1140.     X11_init,
  1141.     X11_locator,
  1142.     X11_mapcolor,
  1143. #ifndef VOGLE
  1144.     X11_setls,
  1145. #endif
  1146.     X11_setlw,
  1147.     X11_string,
  1148.     X11_swapbuf,
  1149.     X11_sync
  1150. };
  1151.  
  1152. /*
  1153.  * _X11_devcpy
  1154.  *
  1155.  *    copy the X11 device into vdevice.dev.
  1156.  */
  1157. int _X11_devcpy(void)
  1158. {
  1159.     vdevice.dev = X11dev;
  1160. }
  1161.